#ifndef ZMEDIASERVER_3RDPART_ZLTOOLKIT_SRC_UTIL_MYSTRING_H
#define ZMEDIASERVER_3RDPART_ZLTOOLKIT_SRC_UTIL_MYSTRING_H
 
#include <string.h>
 
namespace Coolio {
 
class mystring {
public:
	mystring();
	mystring(const mystring& str);
	mystring(const mystring& str, size_t pos, size_t len = npos);
    mystring(const std::string & str);
	mystring(const char* s);
	mystring(const char* s, size_t n);
	mystring(size_t n, char c);
	~mystring();
 
	const char* c_str() const; 
    std::string str() const;
	size_t length() const;
	size_t size() const;
    size_t capacity() const;
    void reserve(size_t size);
	
	char& operator [] (size_t pos);
	const char& operator [] (size_t pos) const;
	mystring& operator = (const mystring& str);
	mystring& operator = (const char* s);
	mystring& operator = (char c);
	mystring& operator += (const mystring& str);
	mystring& operator += (const char* s);
	mystring& operator += (char c);
    
    void push_back(char c);
 
	mystring& append(const mystring& str);
	mystring& append(const char* s,size_t n);
 
	mystring& assign(const mystring& str);
	mystring& assign(const char* s,size_t n);
    
    mystring substr(size_t pos, size_t n = mystring::npos) const;
    
    mystring& erase(size_t pos, size_t n = mystring::npos);
    
    mystring& insert(size_t pos, const char* s, size_t n);
 
	char& at(size_t pos);
	const char& at(size_t pos) const;
 
	void clear();
 
	int compare(const mystring& str) const;
	int compare(const char* s) const;
 
	const char* data() const;
	bool empty() const;
 
	static const size_t npos = -1;
 
private:
	size_t size_;
	char* buffer_;
}; // class mystring
 
inline mystring::mystring(){
	size_ = 0;
	buffer_ = nullptr;
}
 
inline mystring::mystring(const mystring& str){
	size_ = str.size_;
	buffer_ = new char[size_];
	memcpy(buffer_, str.buffer_,size_);	
}

inline mystring::mystring(const std::string & str){
    size_ = str.size();
	buffer_ = new char[size_];
	memcpy(buffer_, str.c_str(),size_);	  
}

inline mystring::mystring(const mystring& str, size_t pos, size_t len){
	if (pos > str.size_) {
		size_ = 0;
		buffer_ = nullptr;
	} else {
		if (pos + len > str.size_)
			size_ = str.size_ - pos;
		else
			size_ = len;
 
		buffer_ = new char[size_];
        memcpy(buffer_,str.c_str()+pos,size_);
		const char* p = str.c_str() + pos;
	}
}
 
inline mystring::mystring(const char* s){
	size_ = strlen(s);
	buffer_ = new char[size_];
	memcpy(buffer_, s,size_);
}
 
inline mystring::mystring(const char* s, size_t n){
	if (strlen(s) <= n) {
		size_ = strlen(s);
		buffer_ = new char[size_];
		memcpy(buffer_, s,size_);
	} else {
		size_ = n;
		buffer_ = new char[size_+1];
		memcpy(buffer_, s, n);
	}
}
 
inline mystring::mystring(size_t n, char c){
	size_ = n;
	buffer_ = new char[size_+1];
	memset(buffer_, c, n);
}
 
inline mystring::~mystring(){
	if (buffer_)
		delete [] buffer_;
	size_ = 0;
}
 
inline const char* mystring::c_str() const{
	return buffer_;
}
inline std::string mystring::str() const{
    return std::string(buffer_,size_);
}
inline size_t mystring::length() const{
	return size_;
}
 
inline size_t mystring::size() const{
	return size_;
}
inline size_t mystring::capacity() const{
	return size_;
}
inline void mystring::reserve(size_t size){
    
}
inline char& mystring::operator [] (size_t pos)
{
	return buffer_[pos];	
}
	
inline const char& mystring::operator [] (size_t pos) const{
	if (pos >= size_)
		throw std::out_of_range("BufferLikeString::substr out_of_range");
	else
		return buffer_[pos];	
}
 
 
inline mystring& mystring::operator = (const mystring& str){
	if (this->size_ != 0)
		delete [] buffer_;
 
	size_ = str.size_;
	buffer_ = new char[size_];
	memcpy(buffer_, str.c_str(),size_);
	return *this;
}
 
inline mystring& mystring::operator = (const char* s){
	if (this->size_ != 0)
		delete [] buffer_;
 
	size_ = strlen(s);
	buffer_ = new char[size_+1];
	memcpy(buffer_, s, size_);
	return *this;
}
 
inline mystring& mystring::operator = (char c){
	if (this->size_ != 1)
		delete [] buffer_;
 
	size_ = 1;
	buffer_ = new char[size_];
	buffer_[0] = c;
	return *this;
}
	
inline mystring& mystring::operator += (const mystring& str){
	
	char* data = new char[size_+str.size_];
	memcpy(data, buffer_,size_);
	memcpy(data+size_, str.buffer_,str.size_);
    
	delete [] buffer_;
	buffer_ = data;
    size_ += str.size_;
	return *this;
}
 
inline mystring& mystring::operator += (const char* s){
    char* data = new char[size_+strlen(s)];
	memcpy(data, buffer_,size_);
	memcpy(data+size_, s, strlen(s));
    
	delete [] buffer_;
	buffer_ = data;
    size_ += strlen(s);
	return *this;
}
 
inline mystring& mystring::operator += (char c){
    char* data = new char[size_+1];
	memcpy(data, buffer_,size_);
	memcpy(data+size_, &c, 1);
    
	delete [] buffer_;
	buffer_ = data;
    size_ += 1;
	return *this;
}

inline void mystring::push_back(char c) {
	char* data = new char[size_+1];
	memcpy(data, buffer_,size_);
	memcpy(data+size_, &c, 1);
	delete [] buffer_;
	buffer_ = data;
    size_ += 1;
}
 
inline mystring& mystring::append(const mystring& str){
	*this += str;
	return *this;
}
 
inline mystring& mystring::append(const char* s,size_t n){
    char* data = new char[size_+n];
	memcpy(data, buffer_,size_);
	memcpy(data+size_, s, n);
    
	delete [] buffer_;
	buffer_ = data;
    size_ += n;
	return *this;
}
 
inline mystring& mystring::assign(const mystring& str){
	*this = str;
	return *this;
}
	
inline mystring& mystring::assign(const char* s,size_t n){    
    if (this->size_ != 0)
		delete [] buffer_;
	size_ = n;
	buffer_ = new char[size_];
	memcpy(buffer_, s, size_);
	return *this;
}

inline mystring mystring::substr(size_t pos, size_t n) const{
    const char * str_p = (const char *)buffer_;
    if (n == mystring::npos) {
        //获取末尾所有的
        if (pos >= size()) {
            throw std::out_of_range("BufferLikeString::substr out_of_range");
        }
        return mystring(str_p+pos,size()-pos);
    }

    //获取部分
    if (pos + n > size()) {
        throw std::out_of_range("BufferLikeString::substr out_of_range");
    }
    return mystring(str_p+pos,size()-pos);
}

inline mystring& mystring::erase(size_t pos, size_t n) {
    if (n == mystring::npos) {
        //删除末尾所有的
        if (pos >= size_) {
            throw std::out_of_range("BufferLikeString::substr out_of_range");
        }
        buffer_[pos] = '\0';
        size_=pos;
        return *this;
    }

    //获取部分
    if (pos + n > size_) {
        throw std::out_of_range("BufferLikeString::substr out_of_range");
    }
    char * str_p = (char *)buffer_;
    memmove(str_p+pos,str_p+n+pos,size_-pos-n);
    buffer_[size_-n] = '\0';
    size_-=n;
    return *this;
}

inline mystring& mystring::insert(size_t pos, const char* s, size_t n){
    if (pos == mystring::npos) {
        char* data = new char[size_+n];
        memcpy(data, buffer_,size_);
        memcpy(data+size_, s,n);
        size_ += n;
        data[size_]='\0';
        delete [] buffer_;
        buffer_ = data;
        return *this;
    }
    char* data = new char[size_+n];
    memcpy(data, buffer_,pos);
    memcpy(data+pos, s,n);
    memcpy(data+pos+n, buffer_+pos ,size_-pos);
    size_ += n;
    data[size_]='\0';
    delete [] buffer_;
    buffer_ = data;
    return *this;
}
inline char& mystring::at(size_t pos){
	return buffer_[pos];
}
	
inline const char& mystring::at(size_t pos) const{
	return buffer_[pos];
}
 
inline void mystring::clear(){
	delete [] buffer_;
	size_ = 0;
	buffer_ = new char[1];
	buffer_[0] = '\0';
}
	
inline int mystring::compare(const mystring& str) const{
	return strcmp(buffer_, str.buffer_);
}
 
inline int mystring::compare(const char* s) const{
	return strcmp(buffer_, s);
}
 
inline const char* mystring::data() const{
	return buffer_;
}
	
inline bool mystring::empty() const{
	return (size_ == 0);
}
 
static inline mystring operator + (const mystring& lhs, const mystring& rhs){
	mystring str(lhs);
	str += rhs;
	return str;
}
 
static inline mystring operator + (const mystring& lhs, const char* rhs){
	mystring str(lhs);
	str += rhs;
	return str;
}
 
static inline mystring operator + (const char* lhs, const mystring& rhs){
	mystring str(lhs);
	str += rhs;
	return str;
}
 
static inline mystring operator + (const mystring& lhs, char rhs){
	mystring str(lhs);
	str += rhs;
	return str;
}
 
static inline mystring operator + (char lhs, const mystring& rhs){
	mystring str(&lhs);
	str += rhs;
	return str;
}
 
static inline bool operator == (const mystring& lhs, const mystring& rhs){
	return (lhs.compare(rhs) == 0);
}
 
static inline bool operator == (const char* lhs, const mystring& rhs){
	return (rhs.compare(lhs) == 0);
}
 
static inline bool operator == (const mystring& lhs, const char* rhs){
	return (lhs.compare(rhs) == 0);
}
 
static inline bool operator != (const mystring& lhs, const mystring& rhs){
	return (lhs.compare(rhs) != 0);
}
 
static inline bool operator != (const char* lhs, const mystring& rhs){
	return (rhs.compare(lhs) != 0);
}
 
static inline bool operator != (const mystring& lhs, const char* rhs){
	return (lhs.compare(rhs) != 0);
}
 
static inline bool operator < (const mystring& lhs, const mystring& rhs){
	return (lhs.compare(rhs) < 0);
}
 
static inline bool operator < (const char* lhs, const mystring& rhs){
	return (rhs.compare(lhs) >= 0);
}
 
static inline bool operator < (const mystring& lhs, const char* rhs){
	return (lhs.compare(rhs) < 0);
}
 
static inline bool operator <= (const mystring& lhs, const mystring& rhs){
	return (lhs.compare(rhs) <= 0);
}
 
static inline bool operator <= (const char* lhs, const mystring& rhs){
	return (rhs.compare(lhs) > 0);
}
 
static inline bool operator <= (const mystring& lhs, const char* rhs){
	return (lhs.compare(rhs) <= 0);
}
 
static inline bool operator > (const mystring& lhs, const mystring& rhs){
	return (lhs.compare(rhs) > 0);
}
 
static inline bool operator > (const char* lhs, const mystring& rhs){
	return (rhs.compare(lhs) <= 0);
}
 
static inline bool operator > (const mystring& lhs, const char* rhs){
	return (lhs.compare(rhs) > 0);
}
 
static inline bool operator >= (const mystring& lhs, const mystring& rhs){
	return (lhs.compare(rhs) >= 0);
}
 
static inline bool operator >= (const char* lhs, const mystring& rhs){
	return (rhs.compare(lhs) < 0);
}
 
static inline bool operator >= (const mystring& lhs, const char* rhs){
	return (lhs.compare(rhs) >= 0);
}
 
} // namespace Coolio
 
#endif // ZMEDIASERVER_3RDPART_ZLTOOLKIT_SRC_UTIL_MYSTRING_H
